﻿using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using Padsurface.Audio.Engine.Interfaces;
using Padsurface.Audio.Song.Repositories.Interfaces;
using Padsurface.Audio.Song.Services;
using Padsurface.Audio.Song.Services.Interfaces;
using Padsurface.Audio.Tests.Unit.Stubs;
using Padsurface.Tests;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Windows.Storage;

namespace Padsurface.Audio.Tests.Unit.SongSaverSpecifications
{
    public abstract class WhenSave : TestBase
    {
        protected ISongSaver SongSaver { get; private set; }
        protected ISongRepository SongRepository { get; private set; }

        protected abstract Song.Model.Song SongToSave { get; }
        protected StorageFile StorageFile { get; set; }

        protected IMetronome Metronome { get; private set; }
        protected IPlayBuffer PlayBuffer { get; private set; }

        protected async override void Arrange()
        {
            StorageFile = await Windows.Storage.ApplicationData.Current.TemporaryFolder.CreateFileAsync("WhenSaveUnitTest", CreationCollisionOption.GenerateUniqueName);

            SongRepository = new SongRepositoryStub();

            SongSaver = new SongSaver(SongRepository);
            Metronome = new MetronomeStub();
            PlayBuffer = new PlayBufferStub();
        }

        protected override void Act()
        {
            EventTrigger = new ManualResetEvent(false);           
            SongSaver.Save(SongToSave, StorageFile).ContinueWith(t => 
            {
                Exception = t.Exception;
                EventTrigger.Set();
            });
        }

        public async override void Cleanup()
        {
            await StorageFile.DeleteAsync();
        }
    }

    [TestClass]
    public class WhenSaveGivenEmptySong : WhenSave
    {
        protected override Song.Model.Song SongToSave { get { return (Song.Model.Song)null; } }

        protected override void Act()
        {
            ExpectException(base.Act);
        }

        [TestMethod]
        public void ThenAnArgumentNullExceptionShouldBeThrown()
        {
            Assert.IsNotNull(Exception);
            Assert.IsNotNull(Exception.InnerException);
            Assert.AreEqual(typeof(ArgumentNullException), Exception.InnerException.GetType());
            Assert.AreEqual((Exception.InnerException as ArgumentNullException).ParamName, "song");
        }
    }
}